﻿/**************************************************************************
创建时间:	2020/5/15
作	  者:	张存
邮 	  箱:	zhangcunliang@126.com

Copyright (c) zhcun.cn

描	述： 自定义TreeView
记	录：
***************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ZhCun.Utils;
using ZhCun.Utils.Helpers;
using ZhCun.Win.Extend;

namespace ZhCun.Win.Controls
{
    public class TreeViewEx : TreeView
    {
        public TreeViewEx()
        {
            Init();
        }

        bool _AllowDropNode;

        void Init()
        {
            HideSelection = false;
            //自已绘制  
            DrawMode = TreeViewDrawMode.OwnerDrawText;
        }

        /// <summary>
        /// 是否允许拖动节点
        /// </summary>
        [Description("是否允许拖动改变节点位置"), Browsable(true)]
        public bool AllowDropNode
        {
            set
            {
                _AllowDropNode = value;
                if (value) AllowDrop = true;
            }
            get
            {
                return _AllowDropNode;
            }
        }

        /// <summary>
        /// 节点直接拖动完整之后触发
        /// </summary>
        [Description("节点直接拖动完成之后触发"), Browsable(true)]
        public event DropNodeEventHandle DropNodeAfter;

        /// <summary>
        /// 节点直接拖动完整之后触发，返回false取消拖动
        /// </summary>
        [Description("节点拖动之前之后触发，返回false取消拖动"), Browsable(true)]
        public event DropNodeEventHandle DropNodeBefore;

        /// <summary>
        /// 当复选框选择时是否单选
        /// </summary>
        [Description("复选框选是否为单选"), Browsable(true)]
        public bool IsSingleChecked { set; get; }

        protected override void OnItemDrag(ItemDragEventArgs e)
        {
            base.OnItemDrag(e);

            if (!AllowDropNode) return;

            if (e.Button == MouseButtons.Left)
            {
                DoDragDrop(e.Item, DragDropEffects.Move);
            }
        }

        protected override void OnDragEnter(DragEventArgs drgevent)
        {
            base.OnDragEnter(drgevent);

            if (!AllowDropNode) return;

            if (drgevent.Data.GetDataPresent(typeof(TreeNode)))
            {
                drgevent.Effect = DragDropEffects.Move;
            }
            else
            {
                drgevent.Effect = DragDropEffects.None;
            }
        }

        protected override void OnDragDrop(DragEventArgs drgevent)
        {
            base.OnDragDrop(drgevent);

            if (!AllowDropNode) return;

            //获得拖放中的节点  
            TreeNode moveNode = (TreeNode)drgevent.Data.GetData(typeof(TreeNode));
            //根据鼠标坐标确定要移动到的目标节点  
            Point pt;
            TreeNode targetNode;
            pt = PointToClient(new Point(drgevent.X, drgevent.Y));
            targetNode = GetNodeAt(pt);

            if (moveNode == targetNode) return;

            if (DropNodeBefore?.Invoke(moveNode, targetNode) == false)
            {
                return;
            }

            //添加结点
            TreeNode newMoveNode = (TreeNode)moveNode.Clone();

            //if (moveNode.Parent == targetNode.Parent && MessageBox.Show(
            //        $"是否移动到 {targetNode.Text} 的子节点?",
            //        "拖动确认",
            //        MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1) != DialogResult.Yes)
            //{
            //    targetNode.Parent.Nodes.Insert(targetNode.Index, newMoveNode);
            //}

            //else
            //{

            //}
            targetNode.Nodes.Insert(targetNode.Nodes.Count, newMoveNode);
            //展开目标节点,便于显示拖放效果  
            targetNode.Expand();
            //更新当前拖动的节点选择  
            SelectedNode = newMoveNode;

            //移除拖放的节点
            moveNode.Remove();

            DropNodeAfter?.Invoke(newMoveNode, targetNode);
        }

        protected override void OnDrawNode(DrawTreeNodeEventArgs e)
        {
            e.DrawDefault = true;
            base.OnDrawNode(e);
        }

        protected override void OnAfterCheck(TreeViewEventArgs e)
        {
            base.OnAfterCheck(e);

            if (!IsSingleChecked) return;

            if (e.Action == TreeViewAction.ByMouse || e.Action == TreeViewAction.ByKeyboard)
            {
                if (e.Node.Checked)
                {
                    this.LoopTreeNode(LoopNode);
                }
            }

            bool LoopNode(TreeNode node)
            {
                if (node.Name != e.Node.Name)
                {
                    node.Checked = false;
                }
                return false;
            }
        }

        /// <summary>
        /// 根据节点名称找到节点
        /// </summary>
        public TreeNode FindNode(string name)
        {
            var nodes = Nodes.Find(name, true);
            if (nodes != null && nodes.Count() > 0)
            {
                return nodes.First();
            }
            return null;
        }
        /// <summary>
        /// 根据指定名称选中节点，并返回选中节点
        /// </summary>
        public TreeNode SetSelectedNode(string name, bool isExpand = true)
        {
            var node = FindNode(name);
            if (node != null)
            {
                SelectedNode = node;
                if (isExpand)
                {
                    node.Expand();
                }
            }
            return node;
        }
        ///// <summary>
        ///// 循环遍历所有节点及子节点，当满足 FindHandle 时退出
        ///// </summary>
        ///// <param name="tv">treeview控件</param>
        ///// <param name="FindHandle">终止条件，为空时遍历所有节点返回false</param>
        ///// <returns>findHandle成立时返回true</returns>
        //public bool LoopTreeNode(Func<TreeNode, bool> FindHandle)
        //{
        //    foreach (TreeNode node in Nodes)
        //    {
        //        if (node.LoopTreeNode(FindHandle))
        //        {
        //            return true;
        //        }
        //    }
        //    return false;
        //}
        ///// <summary>
        ///// 初始化TreeView数据
        ///// </summary>
        ///// <typeparam name="T">数据类型</typeparam>
        ///// <param name="tv">树控件</param>
        ///// <param name="treeData">数据</param>
        ///// <param name="IsRootNode">是否主节点的委托方法</param>
        ///// <param name="IsSubNode">是否子节点的委托方法</param>
        ///// <param name="CreateNode">创建节点的委托方法</param>
        //public void InitTreeViewData<T>(
        //    List<T> treeData,
        //    Func<T, bool> IsRootNode,
        //    Func<T, TreeNode, bool> IsSubNode,
        //    Func<T, TreeNode> CreateNode
        //    )
        //{
        //    Nodes.Clear();
        //    if (treeData == null) return;
        //    foreach (var item in treeData)
        //    {
        //        if (IsRootNode(item))
        //        {
        //            TreeNode tn = CreateNode(item);
        //            Nodes.Add(tn);
        //            LoadSubMenu(tn);
        //        }
        //    }
        //    void LoadSubMenu(TreeNode pNode)
        //    {
        //        foreach (var item in treeData)
        //        {
        //            if (IsSubNode(item, pNode))
        //            {
        //                TreeNode tn = CreateNode(item);
        //                pNode.Nodes.Add(tn);
        //                LoadSubMenu(tn);
        //            }
        //        }
        //    }
        //}

        ///// <summary>
        ///// 初始化菜单树
        ///// </summary>
        //public void InitTreeViewData<TData>(List<TData> treeData, Action<TreeNode, TData> OnNodeAdded = null)
        //    where TData : ITreeModel
        //{
        //    InitTreeViewData(treeData, IsRootNode, IsSubNode, CreateNode);

        //    bool IsRootNode(TData m)
        //    {
        //        return m.PId.IsEmpty();
        //    }
        //    bool IsSubNode(TData m, TreeNode pNode)
        //    {
        //        return m.PId == pNode.Name;
        //    }
        //    TreeNode CreateNode(TData model)
        //    {
        //        TreeNode tn = new TreeNode();
        //        tn.Name = model.Id;
        //        tn.Text = model.Caption;
        //        tn.Tag = model;
        //        OnNodeAdded?.Invoke(tn, model);
        //        return tn;
        //    }
        //}
    }

    public delegate bool DropNodeEventHandle(TreeNode moveNode, TreeNode targetNode);

    ///// <summary>
    ///// TreeNode 扩展方法实现
    ///// </summary>
    //public static class TreeNodeEx
    //{
    //    /// <summary>
    //    /// 循环树节点，当findHandle返回true是退出，返回false则遍历全部
    //    /// </summary>
    //    /// <param name="rootNode">要遍历的主节点</param>
    //    /// <param name="FindHandle">找到节点的委托方法</param>
    //    /// <returns>FindHandle 的返回值</returns>
    //    public static bool LoopTreeNode(this TreeNode rootNode, Func<TreeNode, bool> FindHandle)
    //    {
    //        foreach (TreeNode node in rootNode.Nodes)
    //        {
    //            if (FindHandle?.Invoke(node) == true)
    //            {
    //                return true;
    //            }
    //            else
    //            {
    //                if (LoopTreeNode(node, FindHandle))
    //                {
    //                    return true;
    //                }
    //            }
    //        }
    //        return false;
    //    }
    //}
}